package com.bonc.rms.utils;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.bonc.odk.logmanager.LogManager;


public class JDBCUtil {
	
	private static final String DRIVERNAME;
	private static final String URL;
	private static final String USERNAME;
	private static final String PASSWORD;
	
	static {
		DRIVERNAME = PropertiesUtil.getString("spring.datasource.driverClassName");
		URL = PropertiesUtil.getString("spring.datasource.url");
		USERNAME = PropertiesUtil.getString("spring.datasource.username");
		PASSWORD = PropertiesUtil.getString("spring.datasource.password");
//		DRIVERNAME = "com.mysql.jdbc.Driver";
//		URL = "jdbc:mysql://127.0.0.1:3306/tms";
//		USERNAME = "root";
//		PASSWORD = "root";
	}
	
	/**
	 * get connection !!! remember to close !!!
	 * 
	 * @return
	 */
	public static Connection getConn(){
		Connection conn = null;
		try {
			Class.forName(DRIVERNAME);
			conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
		} catch (SQLException | ClassNotFoundException e) {
			LogManager.Exception("connect to database failed!", e);
		}catch (Exception e) {
			LogManager.Exception("connect to database failed with exception!", e);
		}
		return conn;
	}
	
	/**
	 * close resource
	 * 
	 * @param conn
	 * @param ps
	 * @param rs
	 */
	public static void close(Connection conn,PreparedStatement ps,ResultSet rs){
		if(rs!=null){
			try {
				rs.close();
			} catch (SQLException e) {
				LogManager.Exception("close resultSet failed!", e);
			}
		}
		if(ps!=null){
			try {
				ps.close();
			} catch (SQLException e) {
				LogManager.Exception("close preparedStatement failed!", e);
			}
		}
		if(conn!=null){
			try {
				conn.close();
			} catch (SQLException e) {
				LogManager.Exception("close database connection failed!", e);
			}
		}
	}
	
	public static QueryResult query(String sql, Object ... params) {
		Connection conn = getConn();
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			ps = conn.prepareStatement(sql);
			for(int i = 0; i < params.length; i ++) {
				ps.setObject(i + 1, params[i]);
			}
			rs = ps.executeQuery();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return new QueryResult(conn, ps, rs);
	}
	
	/**
	 * 查询数据库，并返回查询结果
	 * @param sql
	 * @param columnName
	 * @param params
	 * @return
	 */
	public static List<Map<String, Object>> queryList(String sql, String [] columnName, Object ... params) {
		return getData(query(sql, params), columnName);
	}
	
	public static List<Object> queryList(String sql, String columnName, Object ... params) {
		return getData(query(sql, params), columnName);
	}
	
	/**
	 * 该方法用来从 ResultSet 中解析出查询结果
	 * 
	 * @param qr
	 * @param columnName columnName 中保存着查询结果的字段名
	 * @return
	 */
	public static List<Map<String, Object>> getData(QueryResult qr, String [] columnName) {
		
		ResultSet rs = qr.getResultSet();
		
		List<Map<String, Object>> valueList = new ArrayList<Map<String, Object>>();
		Map<String, Object> valueMap = new HashMap<String, Object>();
		try {
			while(rs.next()) {
				for(String str : columnName) {
					valueMap.put(str, rs.getObject(str));
				}
				valueList.add(valueMap);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			qr.close();
		}
		
		return valueList;
	}
	
	public static List<Object> getData(QueryResult qr, String columnName) {
		
		ResultSet rs = qr.getResultSet();
		
		List<Object> valueList = new ArrayList<Object>();
		try {
			while(rs.next()) {
				valueList.add(rs.getObject(columnName));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			qr.close();
		}
		
		return valueList;
	}
	
	/**
	 * the class contains a ResultSet object that you can get data from here, 
	 * but remember to invoke the close method at the end !!!
	 */
	public static class QueryResult{
		
		private Connection conn;
		private PreparedStatement stmt;
		private ResultSet rs;
		
		public QueryResult(Connection conn, PreparedStatement stmt, ResultSet rs) {
			this.conn = conn;
			this.stmt = stmt;
			this.rs = rs;
		}

		public ResultSet getResultSet() {
			return rs;
		}

		public void close() {
			JDBCUtil.close(conn, stmt, rs);
		}
	}
	
}